package com.bruce.ai.alibaba.agentcard.discovery.metrics;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.Map;

/**
 * A2A通信指标收集器
 * 用于收集和跟踪A2A通信的性能指标
 */
public class A2AMetrics {
    
    // 请求计数器
    private final LongAdder totalRequests = new LongAdder();
    private final LongAdder successfulRequests = new LongAdder();
    private final LongAdder failedRequests = new LongAdder();
    private final LongAdder timeoutRequests = new LongAdder();
    private final LongAdder circuitBreakerOpenRequests = new LongAdder();
    
    // 响应时间统计
    private final AtomicLong totalResponseTime = new AtomicLong(0);
    private final AtomicLong minResponseTime = new AtomicLong(Long.MAX_VALUE);
    private final AtomicLong maxResponseTime = new AtomicLong(0);
    
    // 重试统计
    private final LongAdder totalRetries = new LongAdder();
    private final AtomicLong maxRetries = new AtomicLong(0);
    
    // 按Agent分组的指标
    private final Map<String, AgentMetrics> agentMetrics = new ConcurrentHashMap<>();
    
    // 错误统计
    private final Map<String, LongAdder> errorCounts = new ConcurrentHashMap<>();
    
    // 启动时间
    private final Instant startTime = Instant.now();
    
    /**
     * 记录请求开始
     */
    public void recordRequestStart(String agentName) {
        totalRequests.increment();
        getAgentMetrics(agentName).recordRequestStart();
    }
    
    /**
     * 记录请求成功
     */
    public void recordRequestSuccess(String agentName, long responseTimeMs, int retryCount) {
        successfulRequests.increment();
        recordResponseTime(responseTimeMs);
        recordRetryCount(retryCount);
        getAgentMetrics(agentName).recordRequestSuccess(responseTimeMs, retryCount);
    }
    
    /**
     * 记录请求失败
     */
    public void recordRequestFailure(String agentName, String errorCode, long responseTimeMs, int retryCount) {
        failedRequests.increment();
        recordResponseTime(responseTimeMs);
        recordRetryCount(retryCount);
        recordError(errorCode);
        getAgentMetrics(agentName).recordRequestFailure(errorCode, responseTimeMs, retryCount);
    }
    
    /**
     * 记录请求超时
     */
    public void recordRequestTimeout(String agentName, long timeoutMs) {
        timeoutRequests.increment();
        recordResponseTime(timeoutMs);
        getAgentMetrics(agentName).recordRequestTimeout(timeoutMs);
    }
    
    /**
     * 记录熔断器开启
     */
    public void recordCircuitBreakerOpen(String agentName) {
        circuitBreakerOpenRequests.increment();
        getAgentMetrics(agentName).recordCircuitBreakerOpen();
    }
    
    /**
     * 获取总请求数
     */
    public long getTotalRequests() {
        return totalRequests.sum();
    }
    
    /**
     * 获取成功请求数
     */
    public long getSuccessfulRequests() {
        return successfulRequests.sum();
    }
    
    /**
     * 获取失败请求数
     */
    public long getFailedRequests() {
        return failedRequests.sum();
    }
    
    /**
     * 获取超时请求数
     */
    public long getTimeoutRequests() {
        return timeoutRequests.sum();
    }
    
    /**
     * 获取熔断器开启请求数
     */
    public long getCircuitBreakerOpenRequests() {
        return circuitBreakerOpenRequests.sum();
    }
    
    /**
     * 获取成功率
     */
    public double getSuccessRate() {
        long total = getTotalRequests();
        return total > 0 ? (double) getSuccessfulRequests() / total : 0.0;
    }
    
    /**
     * 获取平均响应时间
     */
    public double getAverageResponseTime() {
        long total = getTotalRequests();
        return total > 0 ? (double) totalResponseTime.get() / total : 0.0;
    }
    
    /**
     * 获取最小响应时间
     */
    public long getMinResponseTime() {
        long min = minResponseTime.get();
        return min == Long.MAX_VALUE ? 0 : min;
    }
    
    /**
     * 获取最大响应时间
     */
    public long getMaxResponseTime() {
        return maxResponseTime.get();
    }
    
    /**
     * 获取总重试次数
     */
    public long getTotalRetries() {
        return totalRetries.sum();
    }
    
    /**
     * 获取最大重试次数
     */
    public long getMaxRetries() {
        return maxRetries.get();
    }
    
    /**
     * 获取平均重试次数
     */
    public double getAverageRetries() {
        long total = getTotalRequests();
        return total > 0 ? (double) getTotalRetries() / total : 0.0;
    }
    
    /**
     * 获取运行时间
     */
    public Duration getUptime() {
        return Duration.between(startTime, Instant.now());
    }
    
    /**
     * 获取每秒请求数（QPS）
     */
    public double getQPS() {
        Duration uptime = getUptime();
        long uptimeSeconds = uptime.getSeconds();
        return uptimeSeconds > 0 ? (double) getTotalRequests() / uptimeSeconds : 0.0;
    }
    
    /**
     * 获取指定Agent的指标
     */
    public AgentMetrics getAgentMetrics(String agentName) {
        return agentMetrics.computeIfAbsent(agentName, k -> new AgentMetrics());
    }
    
    /**
     * 获取所有Agent的指标
     */
    public Map<String, AgentMetrics> getAllAgentMetrics() {
        return new ConcurrentHashMap<>(agentMetrics);
    }
    
    /**
     * 获取错误统计
     */
    public Map<String, Long> getErrorCounts() {
        Map<String, Long> result = new ConcurrentHashMap<>();
        errorCounts.forEach((key, value) -> result.put(key, value.sum()));
        return result;
    }
    
    /**
     * 重置所有指标
     */
    public void reset() {
        totalRequests.reset();
        successfulRequests.reset();
        failedRequests.reset();
        timeoutRequests.reset();
        circuitBreakerOpenRequests.reset();
        totalResponseTime.set(0);
        minResponseTime.set(Long.MAX_VALUE);
        maxResponseTime.set(0);
        totalRetries.reset();
        maxRetries.set(0);
        agentMetrics.clear();
        errorCounts.clear();
    }
    
    /**
     * 获取指标摘要
     */
    public MetricsSummary getSummary() {
        return new MetricsSummary(
            getTotalRequests(),
            getSuccessfulRequests(),
            getFailedRequests(),
            getTimeoutRequests(),
            getCircuitBreakerOpenRequests(),
            getSuccessRate(),
            getAverageResponseTime(),
            getMinResponseTime(),
            getMaxResponseTime(),
            getTotalRetries(),
            getAverageRetries(),
            getQPS(),
            getUptime(),
            getErrorCounts()
        );
    }
    
    // 私有方法
    private void recordResponseTime(long responseTimeMs) {
        totalResponseTime.addAndGet(responseTimeMs);
        
        // 更新最小响应时间
        long currentMin = minResponseTime.get();
        while (responseTimeMs < currentMin && !minResponseTime.compareAndSet(currentMin, responseTimeMs)) {
            currentMin = minResponseTime.get();
        }
        
        // 更新最大响应时间
        long currentMax = maxResponseTime.get();
        while (responseTimeMs > currentMax && !maxResponseTime.compareAndSet(currentMax, responseTimeMs)) {
            currentMax = maxResponseTime.get();
        }
    }
    
    private void recordRetryCount(int retryCount) {
        totalRetries.add(retryCount);
        
        // 更新最大重试次数
        long currentMax = maxRetries.get();
        while (retryCount > currentMax && !maxRetries.compareAndSet(currentMax, retryCount)) {
            currentMax = maxRetries.get();
        }
    }
    
    private void recordError(String errorCode) {
        errorCounts.computeIfAbsent(errorCode, k -> new LongAdder()).increment();
    }
    
    /**
     * 单个Agent的指标
     */
    public static class AgentMetrics {
        private final LongAdder requests = new LongAdder();
        private final LongAdder successes = new LongAdder();
        private final LongAdder failures = new LongAdder();
        private final LongAdder timeouts = new LongAdder();
        private final LongAdder circuitBreakerOpens = new LongAdder();
        private final AtomicLong totalResponseTime = new AtomicLong(0);
        private final LongAdder totalRetries = new LongAdder();
        private final Map<String, LongAdder> errorCounts = new ConcurrentHashMap<>();
        
        public void recordRequestStart() {
            requests.increment();
        }
        
        public void recordRequestSuccess(long responseTimeMs, int retryCount) {
            successes.increment();
            totalResponseTime.addAndGet(responseTimeMs);
            totalRetries.add(retryCount);
        }
        
        public void recordRequestFailure(String errorCode, long responseTimeMs, int retryCount) {
            failures.increment();
            totalResponseTime.addAndGet(responseTimeMs);
            totalRetries.add(retryCount);
            errorCounts.computeIfAbsent(errorCode, k -> new LongAdder()).increment();
        }
        
        public void recordRequestTimeout(long timeoutMs) {
            timeouts.increment();
            totalResponseTime.addAndGet(timeoutMs);
        }
        
        public void recordCircuitBreakerOpen() {
            circuitBreakerOpens.increment();
        }
        
        // Getters
        public long getRequests() { return requests.sum(); }
        public long getSuccesses() { return successes.sum(); }
        public long getFailures() { return failures.sum(); }
        public long getTimeouts() { return timeouts.sum(); }
        public long getCircuitBreakerOpens() { return circuitBreakerOpens.sum(); }
        
        public double getSuccessRate() {
            long total = getRequests();
            return total > 0 ? (double) getSuccesses() / total : 0.0;
        }
        
        public double getAverageResponseTime() {
            long total = getRequests();
            return total > 0 ? (double) totalResponseTime.get() / total : 0.0;
        }
        
        public double getAverageRetries() {
            long total = getRequests();
            return total > 0 ? (double) totalRetries.sum() / total : 0.0;
        }
        
        public Map<String, Long> getErrorCounts() {
            Map<String, Long> result = new ConcurrentHashMap<>();
            errorCounts.forEach((key, value) -> result.put(key, value.sum()));
            return result;
        }
    }
    
    /**
     * 指标摘要
     */
    public static class MetricsSummary {
        private final long totalRequests;
        private final long successfulRequests;
        private final long failedRequests;
        private final long timeoutRequests;
        private final long circuitBreakerOpenRequests;
        private final double successRate;
        private final double averageResponseTime;
        private final long minResponseTime;
        private final long maxResponseTime;
        private final long totalRetries;
        private final double averageRetries;
        private final double qps;
        private final Duration uptime;
        private final Map<String, Long> errorCounts;
        
        public MetricsSummary(long totalRequests, long successfulRequests, long failedRequests,
                            long timeoutRequests, long circuitBreakerOpenRequests, double successRate,
                            double averageResponseTime, long minResponseTime, long maxResponseTime,
                            long totalRetries, double averageRetries, double qps, Duration uptime,
                            Map<String, Long> errorCounts) {
            this.totalRequests = totalRequests;
            this.successfulRequests = successfulRequests;
            this.failedRequests = failedRequests;
            this.timeoutRequests = timeoutRequests;
            this.circuitBreakerOpenRequests = circuitBreakerOpenRequests;
            this.successRate = successRate;
            this.averageResponseTime = averageResponseTime;
            this.minResponseTime = minResponseTime;
            this.maxResponseTime = maxResponseTime;
            this.totalRetries = totalRetries;
            this.averageRetries = averageRetries;
            this.qps = qps;
            this.uptime = uptime;
            this.errorCounts = errorCounts;
        }
        
        // Getters
        public long getTotalRequests() { return totalRequests; }
        public long getSuccessfulRequests() { return successfulRequests; }
        public long getFailedRequests() { return failedRequests; }
        public long getTimeoutRequests() { return timeoutRequests; }
        public long getCircuitBreakerOpenRequests() { return circuitBreakerOpenRequests; }
        public double getSuccessRate() { return successRate; }
        public double getAverageResponseTime() { return averageResponseTime; }
        public long getMinResponseTime() { return minResponseTime; }
        public long getMaxResponseTime() { return maxResponseTime; }
        public long getTotalRetries() { return totalRetries; }
        public double getAverageRetries() { return averageRetries; }
        public double getQps() { return qps; }
        public Duration getUptime() { return uptime; }
        public Map<String, Long> getErrorCounts() { return errorCounts; }
        
        @Override
        public String toString() {
            return String.format(
                "MetricsSummary{totalRequests=%d, successRate=%.2f%%, avgResponseTime=%.2fms, qps=%.2f, uptime=%s}",
                totalRequests, successRate * 100, averageResponseTime, qps, uptime
            );
        }
    }
}